﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Transactions;
using KillBill.Business.Entities;
using KillBill.Business.Entities.ListEntities;
using KillBill.Common.Security;
using KillBill.Data.DataAccess;
using KillBill.Services.DTO;

namespace KillBill.Business.Modules.Administration
{
    public class AdministrationManager
    {
        private readonly KillBillEntities _context;

        public AdministrationManager()
        {
            _context = new KillBillEntities();
        }

        #region Customer Operations
        public CustomerList FindCustomerByLastName(string lastName)
        {
            CustomerList customerList = new CustomerList();
            try
            {
                customerList.Customers = _context.Customer
                    .Where(c => c.Person.LastName.Contains(lastName))
                    .ToList();

                customerList.Success = true;
                customerList.Messages.Add(customerList.Customers.Count == 0
                                              ? "No se encontró ningun cliente que concuerde con la informacion ingresada"
                                              : "Clientes encontrados exitosamente");
            }
            catch (Exception)
            {
                customerList.Success = false;
                customerList.Messages.Clear();
                customerList.Messages.Add("Error en la busqueda de clientes");
            }
            return customerList;
        }

        public Customer FindCustomer(string customerID)
        {
            Customer customer;
            try
            {
                customer = _context.Customer
                    .Include("Person")
                    .FirstOrDefault(c => c.CustomerID == customerID && c.IsActive);

                if (customer == null)
                {
                    customer = new Customer();
                    customer.Messages.Add("Cliente no encontrado.");
                    customer.Success = true;
                }
                else
                {
                    customer.Messages.Add("Cliente encontrado.");
                    customer.Success = true;
                }

                return customer;
            }
            catch (Exception ex)
            {
                customer = new Customer();
                customer.Success = false;
                customer.Messages.Add("Ocurrió un error al buscar el cliente.");
                customer.Messages.Add(ex.Message);
                return customer;
            }
        }

        public CustomerList GetCustomers()
        {
            var list = new CustomerList();
            try
            {
                list.Success = true;
                list.Messages.Add("Lista de clientes fue consultada con éxito.");
                list.Customers = _context.Customer.Include("Person").ToList();
            }
            catch (Exception ex)
            {
                list.Success = false;
                list.Messages.Add("La lista de clientes no puede ser obtenida.");
                list.Messages.Add(ex.Message);
            }
            return list;
        }

        public CustomerList FindCustomers(string value)
        {
            if (value == "") return GetCustomers();
            var list = new CustomerList();
            try
            {
                list.Success = true;
                list.Messages.Add("Lista de clientes obtenida exitosamente.");
                list.Customers = _context
                    .Customer
                    .Include("Person")
                    .Where(c => (
                        c.Person.PersonID + " " +
                        c.Person.FirstName + " " +
                        c.Person.LastName + " " +
                        c.Person.Email + " " +
                        c.Person.Address + " " +
                        c.Person.Phone + " " +
                        c.CustomerRUC + " " +
                        c.Reference
                    ).Contains(value))
                    .ToList();
            }
            catch (Exception ex)
            {
                list.Success = false;
                list.Messages.Add("La lista de cleintes no puede ser obtenida.");
                list.Messages.Add(ex.Message);
            }
            return list;
        }

        public KillBillDTO AddCustomer(Customer customer)
        {
            var killBillDto = new KillBillDTO();
            try
            {
                using (var ts = new TransactionScope())
                {
                    customer.Person.ModifiedDate = DateTime.Now;
                    _context.Person.AddObject(customer.Person);
                    _context.AddObject("Customer", customer);
                    _context.SaveChanges();
                    killBillDto.Success = true;
                    killBillDto.Messages.Add("El cliente ha sido agregado con éxito");
                    ts.Complete();
                    return killBillDto;
                }
            }
            catch (Exception ex)
            {
                killBillDto.Success = false;
                killBillDto.Messages.Add("Ocurrió un error al agregar el cliente.");
                killBillDto.Messages.Add(ex.Message);
                return killBillDto;
            }
        }

        public Customer UpdateCustomer(Customer customer)
        {
            try
            {
                using (var ts = new TransactionScope())
                {
                    customer.Person.ModifiedDate = DateTime.Now;
                    _context.Customer.ApplyChanges(customer);
                    _context.SaveChanges();
                    customer.Success = true;
                    customer.Messages.Add("El cliente ha sido actualizado");
                    ts.Complete();
                    return customer;
                }
            }
            catch (Exception ex)
            {
                customer.Success = false;
                customer.Messages.Add("Ocurrió un error al actualizar el cliente.");
                customer.Messages.Add(ex.Message);
                return customer;
            }
        }

        public KillBillDTO DeleteCustomer(Customer customer)
        {
            var killBillDto = new KillBillDTO();
            try
            {
                using (var ts = new TransactionScope())
                {
                    customer.Person.ModifiedDate = DateTime.Now;
                    customer.IsActive = false;
                    _context.Customer.ApplyChanges(customer);
                    _context.SaveChanges();
                    killBillDto.Success = true;
                    killBillDto.Messages.Add("El cliente ha sido eliminado con éxito");
                    ts.Complete();
                    return killBillDto;
                }
            }
            catch (Exception ex)
            {
                killBillDto.Success = false;
                killBillDto.Messages.Add("Ocurrió un error al borrar el cliente.");
                killBillDto.Messages.Add(ex.Message);
                return killBillDto;
            }
        }

        #endregion

        #region Employee Operations
        public EmployeeList GetEmployees()
        {
            var list = new EmployeeList();
            try
            {
                list.Success = true;         
                list.Messages.Add("Lista de empleados fue consultada con éxito.");
                list.Employees = _context.Employee.Include("Person").ToList();
            }
            catch (Exception ex)
            {
                list.Success = false;
                list.Messages.Add("La lista de empleados no puede ser obtenida.");
                list.Messages.Add(ex.Message);                 
            }
            return list;
        }

        public EmployeeList FindEmployees(string value)
        {
            if (value == "") return GetEmployees();
            var list = new EmployeeList();
            try
            {
                list.Success = true;
                list.Messages.Add("Lista de empleados obtenida exitosamente.");
                list.Employees = _context
                    .Employee
                    .Include("Person")
                    .Where(e => (
                        e.Person.PersonID + " " +
                        e.Person.FirstName + " " +
                        e.Person.LastName + " " +
                        e.Person.Email + " " +
                        e.Person.Address + " " +
                        e.Person.Phone + " " +
                        e.EmployeeRoleID
                    ).Contains(value))
                    .ToList();
            }
            catch(Exception ex)
            {
                list.Success = false;
                list.Messages.Add("La lista de empleados no puede ser obtenida.");
                list.Messages.Add(ex.Message);
            }
            return list;
        }

        public Employee FindEmployee(string employeeID)
        {
            Employee employee;
            try
            {
                employee = _context.Employee
                    .Include("Person")
                    .Include("EmployeeActivity")
                    .Include("EmployeeRole")
                    .First(c => c.EmployeeID == employeeID && c.IsActive);

                if (employee == null)
                {
                    employee = new Employee();
                    employee.Messages.Add("Empleado no encontrado.");
                }
                else
                {
                    employee.Messages.Add("Empleado encontrado.");
                }
                employee.Success = true;

                return employee;
            }
            catch (Exception ex)
            {
                employee = new Employee();
                employee.Success = false;
                employee.Messages.Add("Ocurrió un error al buscar el empleado.");
                employee.Messages.Add(ex.Message);
                return employee;
            }
        }

        public KillBillDTO AddEmployee(Employee employee)
        {
            var dto = new KillBillDTO();
            try
            {
                using (var ts = new TransactionScope())
                {
                    dto.Success = true;
                    dto.Messages.Add("El empleado ha sido agregado con éxito");
                    //GeneratePassword(ref employee);
                    //employee.Password = Encryption.EncryptSha256(employee.Password);
                    employee.Person.ModifiedDate = DateTime.Now;                
                    _context.Person.AddObject(employee.Person);
                    _context.AddObject("Employee", employee);
                    _context.SaveChanges();               
                    ts.Complete();
                }
            }
            catch (Exception ex)
            {
                dto.Success = false;
                dto.Messages.Add("Ocurrió un error al agregar el empleado.");
                dto.Messages.Add(ex.Message);
            }
            return dto;
        }

        public Employee UpdateEmployee(Employee employee)
        {
            try
            {
                using (var ts = new TransactionScope())
                {
                    employee.Person.ModifiedDate = DateTime.Now;
                    _context.Employee.ApplyChanges(employee);
                    _context.SaveChanges();
                    employee.Success = true;
                    employee.Messages.Add("El empleado ha sido actualizado");
                    ts.Complete();
                    return employee;
                }
            }
            catch (Exception ex)
            {
                employee.Success = false;
                employee.Messages.Add("Ocurrió un error al actualizar el empleado.");
                employee.Messages.Add(ex.Message);
                return employee;
            }
        }

        public KillBillDTO DeleteEmployee(Employee employee)
        {
            var killBillDto = new KillBillDTO();
            try
            {
                using (var ts = new TransactionScope())
                {
                    employee.Person.ModifiedDate = DateTime.Now;
                    employee.IsActive = false;
                    _context.Employee.ApplyChanges(employee);
                    _context.SaveChanges();
                    killBillDto.Success = true;
                    killBillDto.Messages.Add("El empleado ha sido eliminado con éxito");
                    ts.Complete();
                    return killBillDto;
                }
            }
            catch (Exception ex)
            {
                killBillDto.Success = false;
                killBillDto.Messages.Add("Ocurrió un error al borrar el empleado.");
                killBillDto.Messages.Add(ex.Message);
                return killBillDto;
            }
        }
        public void GeneratePassword(ref Employee employee)
        {
            var password = Guid.NewGuid().ToString().Trim('-').Substring(0, 10);

            MailManager.SendMail(new List<string>() { employee.Person.Email },
                                 new List<string>(),
                                 "Contraseña" + employee.Person.FirstName + " " + employee.Person.LastName,
                                 string.Format("Señor(a):{0} {1}\n\nEste email es una notificación electrónica de que su cuenta" +
                                 " para utilizacion del sistema hasido creada con éxito con los siguientes Datos:\n" +
                                 "Id de Usuario: {2}\nContraseña: {3}\nEs altamente recomendado que cambie su contraseña en su " +
                                 "primer inicio de sesión.", employee.Person.FirstName, employee.Person.LastName, employee.EmployeeID, password));

            password = Encryption.EncryptSha256(password);
            employee.Password = password;
        }
        #endregion

        #region Application Parameters Operations

        public Parameter UpdateParameter(Parameter parameter)
        {
            try
            {
                using (var ts = new TransactionScope())
                {
                    _context.Parameter.AddObject(parameter);
                    _context.SaveChanges();
                    parameter.Success = true;
                    parameter.Messages.Add(parameter.Value + " ha sido guardado con éxito.");
                    ts.Complete();
                    return parameter;
                }
            }
            catch (Exception ex)
            {
                parameter.Messages.Add(parameter.Value + " no pudo ser guardado con éxito.");
                parameter.Messages.Add(ex.Message);
                parameter.Success = false;
                return parameter;
            }
        }
        public Parameter FindParameter(string parameterId)
        {
            Parameter parameter;
            try
            {
                parameter = _context.Parameter
                 .First(p => p.ParameterID == parameterId);
                if (parameter == null)
                {
                    parameter = new Parameter();

                    parameter.Messages.Add("No se encontró el parámetro solicitado");
                }
                else
                {
                    parameter.Messages.Add("Parametro obtenido exitosamente");
                }
                parameter.Success = true;
            }
            catch (Exception ex)
            {
                parameter = new Parameter();
                parameter.Success = false;
                parameter.Messages.Clear();
                parameter.Messages.Add("Error en obtencion de parámetros");
                parameter.Messages.Add(ex.Message);
            }
            return parameter;
        }
        public ParameterList GetParameters()
        {
            var parameterList = new ParameterList();
            try
            {
                parameterList.Parameters = _context.Parameter.ToList();
                if (parameterList.Parameters.Count > 0)
                {
                    parameterList.Messages.Add("Parametros recuperados exitosamente");
                }
                else
                {
                    parameterList.Messages.Add("No se recuperaron parametros");
                }
                parameterList.Success = true;

            }
            catch (Exception)
            {
                parameterList.Success = false;
                parameterList.Messages.Add("Error en la busqueda de parámetros");
            }
            return parameterList;
        }

        #endregion

        #region Application Roles

        public EmployeeRoleList GetAplicactionRoleList()
        {
            var employeeRoleList = new EmployeeRoleList();
            try
            {
                employeeRoleList.Roles = _context.EmployeeRole.ToList();
                employeeRoleList.Messages.Add("Lista de roles fue consultada con éxito.");
                employeeRoleList.Success = true;
                return employeeRoleList;
            }
            catch (Exception ex)
            {
                employeeRoleList.Messages.Add("La lista de roles no puede ser obtenida.");
                employeeRoleList.Messages.Add(ex.Message);
                employeeRoleList.Success = false;
                return employeeRoleList;
            }
        }

        public EmployeeRole AddEmployeeRole(EmployeeRole employeeRole)
        {
            try
            {
                using (var ts = new TransactionScope())
                {
                    _context.EmployeeRole.AddObject(employeeRole);
                    _context.SaveChanges();
                    employeeRole.Messages.Add("Rol agregado con éxito.");
                    employeeRole.Success = true;
                    ts.Complete();
                    return employeeRole;
                }
            }
            catch (Exception ex)
            {
                employeeRole.Messages.Add("El rol no pudo ser agregado.");
                employeeRole.Messages.Add(ex.Message);
                employeeRole.Success = false;
                return employeeRole;
            }
        }

        public EmployeeRole UpdateEmployeeRole(EmployeeRole employeeRole)
        {
            try
            {
                using (var ts = new TransactionScope())
                {
                    _context.EmployeeRole.ApplyChanges(employeeRole);
                    _context.SaveChanges();
                    employeeRole.Messages.Add("El rol fue actualizado con éxito");
                    employeeRole.Success = true;
                    ts.Complete();
                    return employeeRole;
                }
            }
            catch (Exception ex)
            {
                employeeRole.Messages.Add("El nol no pudo ser actualizado");
                employeeRole.Messages.Add(ex.Message);
                employeeRole.Success = false;
                return employeeRole;
            }
        }


        #endregion





    }
}
